﻿//grid
window.gridview = function (json) {
    return new grid().init(json);
}

window.grid = function () {
}

window.grid.prototype = {
    //private datas
    editClass: "editing",
    selectedClass: "selected",
    invisibleClass: "invisible",
    modes: { readonly: "readonly", edit: "edit", editable: "editable", add: "add" },
    rowPermission: { editable: 0x01, checkable: 0x02, deletable: 0x04 },
    attrName: "name",
    attrValue: "value",
    attrSource: "source",
    dataKeyLastText: "lastText",
    dataKeyLastValue: "lastValue",
    types: { text: "text", combo: "combo", checkbox: "checkbox", radio: "radio", date: "date", link: "link" },
    //fields:
    id: undefined,
    container: undefined,
    idMapping: undefined,
    mode: undefined,
    selectable: undefined,
    multipleSelectable: undefined,
    sortable: undefined,
    columns: undefined,
    omitNewTabLink: undefined,
    omitScrollColumn: undefined,
    innerScroll: undefined,
    defaultEmptyRows: undefined,
    //Init
    init: function (json) {
        if (json) {
            this.id = json.id;
            if (!this.id) {
                this.id = "grid" + (100000 * Math.random()) % 99999;
            }
            this.container = json.container;
            this.idMapping = json.idMapping;
            this.mode = json.mode == undefined ? this.modes.readonly : json.mode.toLowerCase();
            this.selectable = json.selectable;
            this.multipleSelectable = json.multipleSelectable;
            this.sortable = json.sortable;
            this.columns = json.columns;
            this.innerScroll = json.innerScroll;
            this.omitNewTabLink = json.omitNewTabLink ? true : false;
            this.omitScrollColumn = json.omitScrollColumn ? true : false;
            this.defaultEmptyRows = json.DefaultEmptyRows ? json.DefaultEmptyRows : 5;

            return this;
        }
    },
    renderCell: function (instance, cellJson, columnJson, forceReadonly) {
        if (instance && cellJson && columnJson) {
            instance.attr(this.attrName, columnJson.Name);
            if (cellJson.CSS) {
                instance.addClass(cellJson.CSS);
            }
            instance.attr(this.attrValue, cellJson.Value);
            if (!forceReadonly && (this.mode == this.modes.add || this.mode == this.modes.edit) && !columnJson.Readonly) {
                var control = this.getEditControl(instance, columnJson.Type, cellJson.Value != undefined ? cellJson.Value : columnJson.DefaultValue, columnJson.Source, columnJson.SourceTextMapping, columnJson.SourceValueMapping);
            }
            else {
                switch (columnJson.Type.toLowerCase()) {
                    case this.types.radio:
                    case this.types.combo:
                    case this.types.date:
                    case this.types.text:
                        instance.text(cellJson.Text);
                        break;
                    case this.types.link:
                        var link = $("<a></a>");
                        link.text(cellJson.Text);
                        link.attr("href", cellJson.Value);
                        if (!this.omitNewTabLink) {
                            link.attr("target", "_blank");
                        }
                        instance.addClass("link").append(link);
                        break;
                    case this.types.checkbox:
                        instance.text(cellJson.Value == true || cellJson.Value == "true" ? "Yes" : "No");
                        break;
                    default:
                        break;
                }
            }
        }
    },
    renderRow: function (instance, rowJson, allowNoData) {
        if (instance && (rowJson || allowNoData)) {
            var gridRow = $("<tr></tr>");

            //insert id column
            var tdCell = $("<th class='identity'></th>");
            if (rowJson) {
                tdCell.text(this.mode == this.modes.add ? "" : rowJson.ID || rowJson.Id || rowJson[this.idMapping]);
            }
            gridRow.append(tdCell);

            //insert check box column for selecting
            if (this.multipleSelectable && (this.mode == this.modes.edit || this.mode == this.modes.readonly)) {
                tdCell = $("<td class='selectable'></td>");
                if (rowJson) {
                    var checkBox = $("<input type='checkbox' />");
                    checkBox.attr(this.attrValue, rowJson.ID);

                    if (this.matchFlag(rowJson.RowPermission, this.rowPermission.checkable)) {
                        checkBox.bind("change", { gridInstance: this }, function (e) {
                            var gridInstance = e.data.gridInstance;
                            var isSelected = $(this).attr("checked");
                            isSelected = (isSelected == true || isSelected == "checked") ? true : false;
                            if (isSelected) {
                                $(this).closest("tr").addClass(gridInstance.selectedClass);
                            } else {
                                $(this).closest("tr").removeClass(gridInstance.selectedClass);
                            }
                            var allRows = gridInstance.tbody.children("tr:not(:disabled)");
                            var selectedRows = allRows.filter(".checked");
                            gridInstance.thead.find("th.selectable>input:checkbox").attr("checked", (allRows.length - selectedRows.length) > 0 ? false : true);
                        });
                    }
                    else {
                        checkBox.attr("disabled", true);
                    }

                    tdCell.append(checkBox);
                }
                gridRow.append(tdCell);
            }

            //insert cells
            for (var j = 0; j < this.columns.length; j++) {
                tdCell = $("<td></td>");
                var currentColumn = this.columns[j];
                if (currentColumn.CSS) {
                    tdCell.addClass(currentColumn.CSS);
                }

                if (rowJson) {
                    if (this.mode == "add" && !currentColumn.Readonly) {
                        this.renderCell(tdCell, { Column: currentColumn.Name, Text: "", Value: "" }, currentColumn);
                    } else {
                        var columnKey = currentColumn.Name;
                        var cellData = rowJson ? this.getCellDataByKey(rowJson.Cells, columnKey) : { Column: currentColumn.Name, Text: "", Value: "" };
                        if (cellData) {
                            this.renderCell(tdCell, cellData, currentColumn);
                        }
                    }
                }
                gridRow.append(tdCell);
            }

            //insert control column
            if (this.mode == this.modes.edit) {
                tdCell = $("<td class='action'></td>");
                if (rowJson && !rowJson.Readonly) {
                    var editButton = this.generateRowEditButton();
                    tdCell.append(editButton);
                }
                gridRow.append(tdCell);
            } else if (this.mode == this.modes.add) {
                tdCell = $("<td class='action'></td>");
                var addButton = this.generateRowDeleteButton();
                tdCell.append(addButton);
                gridRow.append(tdCell);
            }

            if (!this.omitScrollColumn) {
                tdCell = $("<td class='scroll'>&nbsp;</td>");
                gridRow.append(tdCell);
            }

            if (rowJson && (this.selectable || this.multipleSelectable)) {
                gridRow.bind("click", { gridInstance: this }, function (e) {
                    var gridInstance = e.data.gridInstance;
                    if (gridInstance.multipleSelectable) {
                        $(this).find("td.selectable > input:checkbox").click();
                    } else {
                        gridInstance.tbody.children("tr.selected").removeClass(gridInstance.selectedClass);
                        $(this).addClass(gridInstance.selectedClass);
                    }
                });
            }

            instance.append(gridRow);
            return gridRow;
        }
    },
    renderRows: function (instance, rowJson, isHeader) {
        if (instance) {
            var tbody = $("<tbody></tbody>");

            if (rowJson && rowJson.length) {
                for (var i = 0; i < rowJson.length; i++) {
                    this.renderRow(tbody, rowJson[i]);
                }
            } else {
                if (isHeader) {
                    this.renderRow(tbody, undefined, true);
                } else if (this.mode != this.modes.add) {
                    var trCell = $("<tr class='nodata'><td colspan='" + (this.thead.find("th:not(.invisible)").length - 1) + "'>No item.</td></tr>");
                    tbody.append(trCell);
                }
            }
            instance.append(tbody);

            if (!isHeader) {
                this.tbody = tbody;
            }
            return tbody;
        }
    },
    renderHeader: function (instance, columnJson) {
        if (instance) {
            var htmlObject = $("<thead><tr></tr></thead>");
            instance.append(htmlObject);
            htmlObject = htmlObject.children();

            //insert id column
            var thCell = $("<th class='identity'></th>");
            htmlObject.append(thCell);

            //insert check box column for selecting
            if (this.multipleSelectable && (this.mode == this.modes.edit || this.mode == this.modes.readonly)) {
                thCell = $("<th class='selectable'></th>");
                var checkBox = $("<input type='checkbox' />");
                checkBox.attr(this.attrValue, "");
                checkBox.bind("change", { gridInstance: this }, function (e) {
                    var isChecked = $(this).attr("checked");
                    var gridInstance = e.data.gridInstance;
                    if (isChecked == true) {
                        gridInstance.selectAll();
                        gridInstance.tbody.children("tr").addClass(gridInstance.selectedClass);
                    }
                    else {
                        gridInstance.tbody.children("tr").removeClass(gridInstance.selectedClass);
                    }
                });
                thCell.append(checkBox);
                htmlObject.append(thCell);
            }

            //insert columns
            if (columnJson && columnJson.length) {
                for (var i = 0; i < columnJson.length; i++) {
                    var currentCellData = columnJson[i];
                    thCell = $("<th></th>");
                    if (!currentCellData.Visible) {
                        thCell.addClass(this.invisibleClass);
                    }

                    if (currentCellData.Name) {
                        thCell.attr(this.attrName, currentCellData.Name);
                    }
                    if (currentCellData.Source) {
                        thCell.attr(this.attrSource, currentCellData.Source);
                    }

                    if (currentCellData.Title) {
                        thCell.text(currentCellData.Title);
                    }

                    if (currentCellData.CSS) {
                        thCell.addClass(currentCellData.CSS);
                    }

                    htmlObject.append(thCell);
                }
            }

            //insert control column
            if (this.mode == "edit" || this.mode == "add") {
                thCell = $("<th class='action'></th>");
                htmlObject.append(thCell);
            }

            if (!this.omitScrollColumn) {
                thCell = $("<th class='scroll'>&nbsp;</th>");
                htmlObject.append(thCell);
            }

            return htmlObject;
        }
    },
    renderTable: function (json) {
        if (json && this.container) {
            this.container.addClass("bluelotus7-grid-container");
            this.columns = json.Columns ? json.Columns : this.columns;

            if (this.innerScroll) {
                var instance = undefined;

                if (this.headerPart) {
                    this.headerPart.children().remove();
                } else {
                    this.headerPart = $("<div class='thead'></div>");
                }
                if (this.bodyPart) {
                    this.bodyPart.children().remove();
                } else {
                    this.bodyPart = $("<div class='tbody'></div>");
                }
                instance = $("<table class='bluelotus7-grid fixed'></table>");
                this.renderHeader(instance, this.columns);
                this.renderRows(instance, undefined, true);
                this.headerPart.append(instance);
                this.thead = this.headerPart.find("thead");
                instance = $("<table class='bluelotus7-grid fixed'></table>");
                instance.attr("id", this.id);
                instance.data("instance", this);
                this.renderHeader(instance, this.columns);
                this.renderRows(instance, json.Rows);
                this.bodyPart.append(instance);

                this.container.append(this.headerPart);
                this.container.append(this.bodyPart);

                this.instance = instance;
            } else {
                if (!this.instance) {
                    this.instance = $("<table class='bluelotus7-grid'></table>");
                    this.container.append(this.instance);
                } else {
                    this.instance.children().remove();
                }
                this.renderHeader(this.instance, this.columns);
                this.renderRows(this.instance, json.Rows);
            }

            //Handle sort
            if (this.sortable && this.columns.length && this.mode != this.modes.add) {
                var mask = undefined;
                this.instance.tablesorter();
                this.instance.children("thead").find("th:not([name])").removeClass("header").unbind("click");

                if (this.innerScroll) {
                    var headerTable = this.headerPart.children("table");
                    var thisRef = this;

                    headerTable.tablesorter();

                    headerTable.children("thead").find("th").each(function (i, c) {
                        c = $(c);
                        if (c.attr("name")) {
                            //c.addClass("header");
                            c.bind("click", { table: thisRef.instance, index: i }, function (e) {
                                e.data.table.children("thead").find("th").eq(i).click();
                            });
                        } else {
                            c.removeClass("header").unbind("click");
                        }
                    });
                }
            }
            return instance;
        }
    },
    removeSortable: function (nameKey) {
        if (nameKey) {
            var header = this.instance.children("thead").find("th:[name='" + nameKey + "']");
            if (header) {
                header.removeClass("header").unbind("click");
            }
            header = this.thead.find("th:[name='" + nameKey + "']");
            if (header) {
                header.removeClass("header").unbind("click");
            }
        }
    },
    renderEmptyTable: function () {
        if (this.columns) {
            this.renderTable({
                Columns: this.columns,
                Rows: []
            });
            if (this.defaultEmptyRows) {
                for (var i = 0; i < this.defaultEmptyRows; i++) {
                    this.addRowForEdit();
                }
            }
        }
    },
    addRowForEdit: function () {
        if (!this.tbody) {
            this.tbody = $("#" + this.id + " > tbody");
        }

        if (this.tbody) {
            return this.renderRow(this.tbody);
        }
    },
    enableCellEdit: function (cellInstance, columnInfo, ignoreReadonly) {
        if (cellInstance && columnInfo && (!columnInfo.Readonly || ignoreReadonly) && columnInfo.Type != 'link') {
            cellInstance.data("lastText", cellInstance.text());
            var currentValue = cellInstance.attr(this.attrValue);
            cellInstance.data("lastValue", currentValue);
            cellInstance.children().remove();
            cellInstance.html("");
            return this.getEditControl(cellInstance, columnInfo.Type, (currentValue != undefined && currentValue != null) ? currentValue : columnInfo.DefaultValue, columnInfo.Source, columnInfo.SourceTextMapping, columnInfo.SourceValueMapping);
        }
    },
    enableRowEdit: function (rowInstance) {
        var cells = rowInstance.children("td:not(.invisible)");
        if (cells && cells.length) {
            for (var i = 0; i < cells.length; i++) {
                var c = cells.eq(i);
                var columnInfo = this.getColumnInfoByKey(c.attr("name"));
                if (columnInfo && !columnInfo.Readonly) {
                    var control = this.enableCellEdit(c, columnInfo);
                }
            }
            rowInstance.children("td:first").children().addClass(this.editClass);
        }
    },
    getColumnInfoByKey: function (key) {
        if (key && this.columns) {
            for (var i = 0; i < this.columns.length; i++) {
                if (this.columns[i].Name == key) {
                    return this.columns[i];
                }
            }
        }
    },
    getCellDataByKey: function (cells, key) {
        if (cells && key) {
            for (var i = 0; i < cells.length; i++) {
                if (cells[i].Column == key) {
                    return cells[i];
                }
            }
        }
    },
    getEditControl: function (cellInstance, type, value, source, textMapping, valueMapping, css) {
        if (cellInstance && type) {
            var control = undefined;
            cellInstance.addClass(this.editClass);
            type = type.toLowerCase();
            switch (type) {
                case this.types.text:
                    control = $("<input type='text' maxlength='400' />");
                    control.addClass("text");
                    if (value) {
                        control.val(value);
                    }
                    break;
                case this.types.radio:
                    control = window.dataSource.getRadioSource(source, textMapping, valueMapping, value, css);
                    break;
                case this.types.combo:
                    control = window.dataSource.getComboSource(source, textMapping, valueMapping, value, css);
                    break;
                case this.types.date:
                    control = $("<input type='date' />");
                    control.addClass("datepicker");
                    if (value) {
                        control.val(value);
                    }
                    control.datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true });
                    break;
                case this.types.checkbox:
                    control = $("<input type='checkbox' />");
                    if (value == "true" || value == true) {
                        control.attr("checked", true);
                    }
                    break;
                case this.types.link:
                    //Do nothing.
                    break;
                default:
                    break;
            }

            if (control) {
                cellInstance.append(control);
            }
            return control;
        }
    },
    setCellValue: function (cellInstance, value) {
        if (cellInstance) {
            var name = cellInstance.attr("name");
            if (name) {
                var columnInfo = this.getColumnInfoByKey(name);
                if (columnInfo) {
                    switch (columnInfo.Type.toLowerCase()) {
                        case this.types.radio:
                            cellInstance.find("input[value='" + value + "']").attr("checked", true);
                            break;
                        case this.types.combo:
                            cellInstance.find("select").val(value);
                            break;
                        case this.types.date:
                        case this.types.text:
                            cellInstance.find("input:text").val(value ? value : "");
                            break;
                        case this.types.checkbox:
                            value = (value == true || value == "true");
                            cellInstance.find("input").attr("checked", value);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    },
    getRowData: function (rowInstance, valueOnly, useForce, isMixed) {
        if (rowInstance) {
            var json = {};
            var cells = rowInstance.children("td");
            json[this.idMapping ? this.idMapping : "id"] = $(cells[0]).text();
            var startIndex = 1;
            if (this.multipleSelectable) {
                startIndex++;
                json.isSelected = $(cells[0]).children().attr("checked");
            }
            var valueCount = 0;
            for (var i = startIndex; i < cells.length; i++) {
                var current = cells[i];
                current = $(current);
                var mappingName = current.attr("name");

                if (mappingName) {
                    var v = undefined;
                    if (current.hasClass(this.editClass)) {
                        v = this.getCellData(current, useForce);
                        if (v != undefined) {
                            valueCount++;
                            json[mappingName] = valueOnly ? v.value : v;
                        }
                    }
                    else {
                        v = current.attr(this.attrValue);
                        if (v != undefined && (!isMixed || useForce)) {
                            valueCount++;
                            json[mappingName] = valueOnly ? v : { value: v, text: current.text() };
                        }
                    }
                }
            }
            if (!valueCount) {
                json = undefined;
            }
            return json;
        }
    },
    getCellData: function (cellInstance, useForce) {
        var result = undefined;
        if (cellInstance) {
            var mappingName = cellInstance.attr(this.attrName);

            if (mappingName) {
                if (cellInstance.hasClass(this.editClass)) {
                    var columnInfo = this.getColumnInfoByKey(mappingName);
                    if (columnInfo) {
                        switch (columnInfo.Type.toLowerCase()) {
                            case "radio":
                                var checkedRadio = cellInstance.find(":checked");
                                result = { value: checkedRadio.val(), text: checkedRadio.parent().text() };
                                break;
                            case "combo":
                                result = { value: cellInstance.children().val(), text: cellInstance.find(":selected").text() };
                                break;
                            case "date":
                            case "text":
                                result = { value: cellInstance.children().val(), text: cellInstance.children().val() };
                                break;
                            case "checkbox":
                                result = cellInstance.children().attr("checked") ? { value: true, text: "Yes"} : { value: false, text: "No" };
                                break;
                            default:
                                break;
                        }
                    }

                    if (result && result.value == cellInstance.data("lastValue") && !useForce) {
                        result = undefined;
                    }
                }
                else {
                    result = { value: cellInstance.attr(this.attrValue), text: cellInstance.text() };
                }
            }
        }

        return result;
    },
    getUpdatedRowsData: function () {
        var result = new Array();
        var rows = this.tbody.children();
        for (var i = 0; i < rows.length; i++) {
            result.push(this.getRowData(rows.eq(i), true, false));
        }
        return result;
    },
    getSelectedRows: function () {
        if (this.selectable || this.multipleSelectable) {
            return this.tbody.children("tr.selectable");
        }
    },
    getSelectedRowIdentites: function () {
        if (this.multipleSelectable) {
            var checkboxes = this.tbody.children("tr").children("td.selectable").children("input:checked");
            var result = new Array();
            for (var i = 0; i < checkboxes.length; i++) {
                result.push(checkboxes.eq(i).val());
            }
            return result;
        }
    },
    getAllRowIdentites: function (separator) {
        var cells = this.tbody.children("tr").children("td.identity");
        var result = new Array();
        for (var i = 0; i < cells.length; i++) {
            result.push(cells.eq(i).text());
        }
        if (separator) {
            return result.join(separator);
        } else {
            return result;
        }
    },
    generateRowDeleteButton: function (removeFn) {
        var editButton = $("<div title='Delete'></div>");
        editButton.addClass("icon-delete");
        editButton.bind("click", { gridInstance: this, removeFn: removeFn }, function (e) {
            if (removeFn) {
                e.data.removeFn(e, $(this), e.data.gridInstance);
            }
            else {
                $(this).parent().parent().remove();
            }
        });
        return editButton;
    },
    generateRowEditButton: function () {
        var editButton = $("<div title='Edit'></div>");
        editButton.addClass("icon-edit");
        editButton.bind("click", { gridInstance: this }, function (e) {
            var gridInstance = e.data.gridInstance;
            if (gridInstance) {
                gridInstance.enableRowEdit($(this).parent().parent());
                var cell = $(this).parent("td");
                $(this).remove();
                var submitButton = gridInstance.generateRowUpdateButton();
                if (submitButton) {
                    cell.append(submitButton);
                }
                var cancelButton = gridInstance.generateRowCancelButton();
                if (cancelButton) {
                    cell.append(cancelButton);
                }
            }
        });
        return editButton;
    },
    generateRowUpdateButton: function () {
        var submitButton = $("<div title='Save'></div>");
        submitButton.addClass("icon-submit");
        submitButton.bind("click", { gridInstance: this }, function (e) {
            var gridInstance = e.data.gridInstance;
            if (gridInstance) {
                var rowInstance = $(this).parent().parent();
                var data = gridInstance.getRowData(rowInstance);

                if (gridInstance.ajaxUrlForDataUpdate) {
                    $.ajax({
                        url: gridInstance.ajaxUrlForDataUpdate,
                        async: true,
                        data: JSON.stringify(data),
                        type: 'POST',
                        contentType: 'application/json',
                        dataType: 'json',
                        success: function (result, textStatus, jqXHR) {
                            if (result) {
                                if (result.IsSuccess) {
                                    gridInstance.applyRowValue(rowInstance, true);
                                }
                                else {
                                    alert(result.Message);
                                }
                            }
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            alert(errorThrown);
                        }
                    });
                } else {
                    gridInstance.applyRowValue(rowInstance, true);
                }
            }
        });
        return submitButton;
    },
    generateRowCancelButton: function () {
        var submitButton = $("<div title='Cancel'></div>");
        submitButton.addClass("icon-cancel");
        submitButton.bind("click", { gridInstance: this }, function (e) {
            var gridInstance = e.data.gridInstance;
            if (gridInstance) {
                var rowInstance = $(this).parent().parent();
                var data = gridInstance.getRowData(rowInstance);
                gridInstance.applyRowValue(rowInstance, false);
            }
        });
        return submitButton;
    },
    applyGridValues: function (acceptValue) {
        if (this.tbody) {
            var thisRef = this;
            this.tbody.children().each(function (i, c) {
                thisRef.applyRowValue($(c), acceptValue);
            });
        }
    },
    applyRowValue: function (rowInstance, accpetValue) {
        if (rowInstance) {
            var cells = rowInstance.children("td[name]");
            if (cells && cells.length) {
                for (var i = 0; i < cells.length; i++) {
                    var c = cells.eq(i);
                    if (c.hasClass("disabled") || c.hasClass("link")) {
                        continue;
                    }
                    if (accpetValue) {
                        var v = this.getCellData(c, true);
                        if (v) {
                            c.attr(attrValue, v.value);
                            c.children().remove();
                            c.text(v.text);
                        }
                    }
                    else {
                        c.text(c.data("lastText"));
                    }
                }
                var actionCell = rowInstance.children(".action");
                if (actionCell) {
                    actionCell.children().remove();
                    actionCell.append(this.generateRowEditButton());
                }
            }
        }
    },
    addEmptyColumn: function (title, name, type, defaultValue, sourceKey, textMapping, valueMapping) {
        if (title && name && type) {
            var headCell = $("<th></th>");
            var bodyCell = $("<td></td>");
            headCell.attr("name", name).text(title);

            var control = this.getEditControl(bodyCell, type, defaultValue, sourceKey, textMapping, valueMapping);
            bodyCell.append(control);
            var firstClass = "identity";
            firstClass = this.multipleSelectable ? "selectable" : firstClass;

            this.instance.children("thead").children().children("." + firstClass).first().after(headCell);
            var cells = this.tbody.children("tr").children("td." + firstClass);
            if (cells && cells.length) {
                cells.after(bodyCell.clone());
            }
        }
    },
    selectAll: function () {
        this.tbody.find("tr.selectable > td.selectable > input:checkbox:not(:disabled)").attr("checked", true);
    },
    unselectAll: function () {
        this.tbody.find("tr.selectable > td.selectable > input:checkbox:not(:disabled)").attr("checked", false);
    },
    setSelected: function (selectedIdentities, isMerge) {
        var checkboxes = this.instance.find("td.selectable>input:checkbox");
        if (selectedIdentities && selectedIdentities.length) {
            var selectedItems = selectedIdentities.clone();
            this.instance.find("td.selectable>input:checkbox").each(function (i, c) {
                if (selectedItems.length) {
                    for (var i = 0; i < selectedItems.length; ) {
                        if (selectedItems[i] == $(c).val()) {
                            $(c).attr("checked", true);
                            selectedItems.removeAt(i);
                            break;
                        } else {
                            i++
                            if (!isMerge) {
                                $(c).attr("checked", false);
                            }
                        }
                    }
                } else {
                    $(c).attr("checked", false);
                }
            });
            this.thead.find("th.selectable>input:checkbox").attr("checked", (checkboxes.length != 0 && checkboxes.filter(":checked").length == checkboxes.length));

        }
    },
    switchColumnMode: function (columnName, isViewMode, defaultValue) {
        var columnInfo = this.getColumnInfoByKey(columnName);
        if (columnInfo) {
            var cells = this.tbody.find("td[name='" + columnInfo.Name + "']");
            if (cells) {
                for (var i = 0; i < cells.length; i++) {
                    var c = cells.eq(i);
                    if (isViewMode && c.hasClass(this.editClass)) {

                    }
                    else if (!isViewMode && !c.hasClass(this.editClass)) {
                    }
                }
            }
        }
    },
    switchColumnStatus: function (columnName, isDisabled, defaultValue) {
        var columnInfo = this.getColumnInfoByKey(columnName);
        if (columnInfo) {
            var cells = this.tbody.find("td[name='" + columnInfo.Name + "']");
            if (cells) {
                for (var i = 0; i < cells.length; i++) {
                    var c = cells.eq(i);
                    if (c.hasClass(this.editClass)) {
                        c.find("input,select").attr("disabled", isDisabled ? true : false);
                        c.find("button.ui-button").attr("disabled", isDisabled ? true : false);
                        if (defaultValue != undefined && defaultValue != null) {
                            this.setCellValue(c, defaultValue);
                        }
                    }
                }
            }
        }
    },
    switchRowStatus: function (rowInstance, isDisabled, dataJsonObject, idValue) {
        if (rowInstance) {
            if (idValue != undefined && idValue != null) {
                rowInstance.children("td.identity").text(idValue);
            }
            for (var i = 0; i < this.columns.length; i++) {
                var data = dataJsonObject[this.columns[i].Name];
                var cell = rowInstance.find("td[name='" + this.columns[i].Name + "']");
                if (data != undefined && data != null) {
                    this.setCellValue(cell, data);
                    cell.find("input,select").attr("disabled", isDisabled ? true : false);
                    cell.find("button.ui-button").attr("disabled", isDisabled ? true : false);
                }
            }
        }
    },
    removeQuickSetHeader: function (columnKey) {
        if (columnKey) {
            var columnInfo = this.getColumnInfoByKey(columnKey);
            if (columnInfo) {
                var header = this.instance.children("thead").find("th[name='" + columnKey + "']");
                if (header) {
                    header.find("div.quickset").remove();
                }
            }
        }
    },
    initQuickSetHeader: function (columnKey, css, itemFn) {
        if (columnKey) {
            var columnInfo = this.getColumnInfoByKey(columnKey);
            if (columnInfo && columnInfo.Source) {
                var items = undefined;
                switch (columnInfo.Type.toLowerCase()) {
                    case "radio":
                        items = dataSource.getRadioSource(columnInfo.Source, undefined, undefined, undefined, css);
                        break;
                    case "checkbox":
                        items = dataSource.getBooleanSource(columnInfo.Source, undefined, undefined, undefined, css);
                        break;
                    default:
                        break;
                }
                var header = this.thead.find("th[name='" + columnKey + "']");
                if (items && header) {
                    items.addClass("quickset");
                    header.append(items);
                    items.children().bind("click", { gridInstance: this, columnKey: columnKey }, function (e) {
                        var grid = e.data.gridInstance;
                        var columnKey = e.data.columnKey;
                        var index = $(this).parent().children().index($(this));
                        if (grid && columnKey) {
                            var cells = grid.tbody.find("td[name='" + columnKey + "']");
                            for (var i = 0; i < cells.length; i++) {
                                var current = cells.eq(i).find("input").eq(index).attr("checked", true);
                                if (itemFn) {
                                    itemFn(current);
                                }
                            }
                        }
                    });
                }
            }
        }
    },
    matchFlag: function (value, flag) {
        if (value && flag) {
            return value & flag;
        }
        return false;
    },
    // initData format:
    // {
    //      panelUI:jQuery DOM object,
    //      buttons:JSON object,
    //      submitUrl: string,
    //      openFn:function,
    //      height: 300,
    //      width: 350,
    //      modal: true,
    //      draggable: false,
    //      title: string
    // }
    bindAddForCombo: function (comboContainer, initData) {
        if (comboContainer && initData) {
            var button = comboContainer.children("button:last");
            if (button && button.hasClass("ui-button") && button.hasClass("ui-widget")) {
                var addBtn = $("<div></div>");
                addBtn.addClass("combo-add");
                addBtn.insertAfter(button);

                addBtn.bind("click", { addBtn: addBtn, comboSelectObject: comboContainer.children("select"), initData: initData }, function (e) {
                    var selectObject = e.data.comboSelectObject;
                    var addButton = e.data.addBtn;
                    var initData = e.data.initData;

                    if (selectObject) {
                        var source = selectObject.attr("source");
                        if (source) {
                            var randomId = "addCombo_" + getRandom(10000).toString();
                            if (initData.panelUI) {
                            }
                            else {
                                var panelDom = $("<div></div>");
                                panelDom.attr("id", randomId);
                                panelDom.append($("<div><label>Name: </label><input name='name' type='text' value='' /></div>"));

                                var dialogInstance = undefined;
                                dialogInstance = panelDom.dialog({
                                    autoOpen: true,
                                    height: initData.height ? initData.height : 300,
                                    width: initData.width ? initData.width : 350,
                                    modal: initData.modal == undefined ? true : initData.modal,
                                    draggable: initData.draggable == undefined ? false : initData.draggable,
                                    title: initData.title ? initData.title : "Create New Item",
                                    resizable: false,
                                    open: initData.openFn ? initData.openFn : undefined,
                                    buttons: initData.buttons ? buttons : {
                                        "Submit": function () {
                                            var data = {};
                                            panelDom.find("input[name]").each(function (i, c) {
                                                c = $(c);
                                                var key = c.attr("name");
                                                data[key] = c.val();
                                            });
                                            if (initData.submitUrl) {
                                                $.ajax({
                                                    url: initData.submitUrl,
                                                    async: true,
                                                    data: data,
                                                    type: 'POST',
                                                    contentType: 'application/json',
                                                    dataType: 'json',
                                                    success: function (result, textStatus, jqXHR) {
                                                        if (result) {
                                                            if (result.IsSuccess) {
                                                                if (result.Data.Key) {
                                                                    dataSource.updateSources(result.Data.Key, result.Data.Items);
                                                                    var newOptions = dataSource.getComboSource(result.Data.Key);

                                                                    $("select[source='" + result.Data.Key + "']").each(function (i, c) {
                                                                        var selected = c.val();
                                                                        c.children().remove();
                                                                        c.append(newOptions.children());
                                                                        c.val(selected);
                                                                    });

                                                                    dialogInstance.dialog("destroy");
                                                                }
                                                            }
                                                            else {
                                                                alert(result.Message);
                                                            }

                                                        }
                                                    },
                                                    error: function (jqXHR, textStatus, errorThrown) {
                                                        alert(errorThrown);
                                                    }
                                                });
                                            } else {
                                                //for local change only
                                                var s = dataSource.getSource(source);
                                                if (s) {
                                                    var v = panelDom.find("input[name]:first").val();
                                                    s.push({ Key: v, Value: v });
                                                    $("select[source='" + source + "']").each(function (i, c) {
                                                        c = $(c);
                                                        var selected = c.val();
                                                        c.children().remove();
                                                        c.append(dataSource.getComboSource(source).children());
                                                        c.val(selected);
                                                    });
                                                    dialogInstance.dialog("destroy");
                                                }
                                            }
                                        },
                                        "Cancel": function () {
                                            dialogInstance.dialog("destroy");
                                        }
                                    }
                                });
                            }
                        }
                    }
                });
            }
        }
    }
}
